package com.example.media.advice;

import com.example.media.constant.RedisKey;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestControllerAdvice
@Slf4j
public class CommonRestControllerAdvice implements ResponseBodyAdvice<ResponseBody> {
    private final JavaMailSender javaMailSender;
    private final ObjectMapper objectMapper;
    private final RedisTemplate redisTemplate;

    public CommonRestControllerAdvice(JavaMailSender javaMailSender, ObjectMapper objectMapper, RedisTemplate redisTemplate) {
        this.javaMailSender = javaMailSender;
        this.objectMapper = objectMapper;
        this.redisTemplate = redisTemplate;
    }

    @ExceptionHandler(value = RuntimeException.class)
    public ResponseEntity exception(RuntimeException e) throws MessagingException, JsonProcessingException {
        log.error("服务器发生异常", e);
        if (!redisTemplate.hasKey(RedisKey.EXCEPTION_MESSAGE + e.getMessage())) {
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            String text = objectMapper.writeValueAsString(e);
            helper.setText(text, true);
            helper.setTo("1051477653@qq.com");
            helper.setFrom("1051477653@qq.com");
            helper.setSubject("视频服务器发生异常通知邮件");
            helper.setCc("renyunku@qq.com");
            javaMailSender.send(mimeMessage);
            redisTemplate.opsForValue().set(RedisKey.EXCEPTION_MESSAGE + e.getMessage(), text, 60, TimeUnit.MINUTES);
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e);
    }

    //业务异常
    @ExceptionHandler(value = MyException.class)
    public ResponseEntity sslException(MyException e) {
        return ResponseEntity.status(250).body(e);
    }


    /**
     * 处理推送超时异常
     *
     * @param a
     * @return
     */
    @ExceptionHandler(value = AsyncRequestTimeoutException.class)
    public ResponseEntity handleAsyncRequestTimeoutException(AsyncRequestTimeoutException a) {
        log.error("sse请求超时");
        return ResponseEntity.ok(SseEmitter.event().data("", MediaType.APPLICATION_JSON).build().stream()
                .map(d -> d.getData().toString())
                .collect(Collectors.joining()));
    }


    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return false;
    }

    @Nullable
    @Override
    public ResponseBody beforeBodyWrite(@Nullable ResponseBody responseBody, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        return null;
    }


}
